package com.getword.service.impl;

import com.getword.domain.Article;
import com.getword.domain.User;
import com.getword.mongodao.ArticleRepository;
import com.getword.mongodao.UserRepository;
import com.getword.service.UserService;
import com.getword.utils.PathUtil;
import com.getword.utils.SpringContextUtil;
import com.getword.web.model.Result;
import com.getword.web.model.ResultCode;
import com.getword.web.model.UserQueryCondition;
import com.mongodb.client.result.UpdateResult;
import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;


@Service
//@Transactional(readOnly = false)
public class UserServiceImpl implements UserService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private MongoOperations mongoOperations;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ArticleRepository articleRepository;

    @Override
    public Result addUser(User user) {
        // 判断用户登录名是否存在
        User user1 = userRepository.findByLoginName(user.getLoginName());
        if (user1 != null) {
            return Result.fail(ResultCode.PARAM_IS_INVALID.getCode(), "该用户名已存在", null);
        }
        user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
        User save = userRepository.save(user);
        return Result.success(save, null);
    }

    // {username, gender,birthday,school,intro, password}
    @Override
    public Result updateUser(User user) {
        if (user.getId() <= 0) {
            return Result.fail(ResultCode.PARAM_IS_INVALID.getCode(), "缺少用户id", null);
        }
        // 判断新的用户登录名是否存在
        User exists = userRepository.findUserByLoginNameAndIdNot(user.getLoginName(), user.getId());
        if (exists != null) {
            return Result.fail(ResultCode.PARAM_IS_INVALID.getCode(), "用户名已经存在", null);
        }
        Update update = new Update();
        if (StringUtils.isNotBlank(user.getUsername()))  // 用户名
            update.set("username", user.getUsername());
        if (StringUtils.isNotBlank(user.getGender()))    // gender
            update.set("gender", user.getGender());
        if (user.getBirthday() != null)                    // 生日
            update.set("birthday", user.getBirthday());
        if (user.getSchool() != null)                      // 学校
            update.set("school", user.getSchool());
        if (user.getRegisterTime() != null) {                // 注册时间
            update.set("registerTime", user.getRegisterTime());
        }
        if (StringUtils.isNotBlank(user.getRole())) {
            if (user.getRole().equals("学生")) {
                user.setRole("ROLE_student");
            } else if (user.getRole().equals("教师")) {
                user.setRole("ROLE_teacher");
            } else {
                user.setRole("ROLE_admin");
            }
            update.set("role", user.getRole());
        }
        // 密码
        if (StringUtils.isNotBlank(user.getPassword())) {
//            user.setPassword(passwordEncoder.encode(user.getPassword()));
            update.set("password", passwordEncoder.encode(user.getPassword()));
        }
        update.set("intro", user.getIntro());           // 简介
        Query query = Query.query(Criteria.where("id").is(user.getId()));
        UpdateResult result = mongoOperations.updateFirst(query, update, User.class);
        if (result.getModifiedCount() > 0) {
            return Result.success(user);
        }
        if (result.getMatchedCount() > 0) {
            return Result.fail("未做更新");
        }
        return Result.fail("更新失败");
    }

    @Override
    public Result getUsers() {
        List<User> users = userRepository.findAll();
        return Result.success(users, null);
    }

    @Override
    public Result count() {
        long count = userRepository.count();
        return Result.success(count, null);
    }

    @Override
    public Result login(User user) {
//        user.setPassword(passwordEncoder.encode(user.getPassword()));

        User u = userRepository.findByLoginName(user.getLoginName());
        if (u == null) {
            return Result.fail("用户名不存在");
        }
        if (passwordEncoder.matches(u.getPassword(), user.getPassword())) {
            return Result.success(u);
        } else {
            return Result.fail("密码错误");
        }
    }

    @Override
    public Result updatePwd(String oldPwd, String pwd) {
        if (oldPwd.equals(pwd)) {
            return Result.fail("新密码不能和旧密码一样");
        }
        User loginUser = SpringContextUtil.getLoginUser();
        User user = userRepository.findUserById(loginUser.getId());
        boolean matches = passwordEncoder.matches(oldPwd, user.getPassword());
        if (!matches) {
            return Result.fail("原密码错误");
        }
        User updateUser = new User(user.getId());
        updateUser.setPassword(pwd);
        UpdateResult result = userRepository.updateUser(updateUser);
        if (result.getModifiedCount() > 0) {
            return Result.success(updateUser);
        }
        return Result.fail("修改密码失败");
    }

    @Override
    public Result uploadHead(MultipartFile file) {
        String uploadPath = "";
        try {
            uploadPath = ResourceUtils.getURL("classpath:static").getPath() + "/upload/user/images/";
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if ("".equals(uploadPath)) {
            return Result.fail("服务器异常");
        }
        String fileExt = PathUtil.getFileExt(file.getOriginalFilename());
        User loginUser = SpringContextUtil.getLoginUser();
        // 查询
        User user = userRepository.findUserById(loginUser.getId());
        String filename = user.getId() + "." + fileExt;
//        System.out.println(uploadPath);
//        System.out.println(filename);
        Query query = Query.query(Criteria.where("id").is(user.getId()));
        mongoOperations.updateFirst(query, Update.update("image", "/upload/user/images/" + filename), User.class);
        try {
            file.transferTo(new File(uploadPath + filename));
            return Result.success(new HashMap<String, String>() {{
                put("filename", file.getOriginalFilename());
                put("imgUrl", "/upload/user/images/" + filename);
            }});
        } catch (IOException e) {
            e.printStackTrace();
            return Result.fail("服务器异常！");
        }
    }

    @Override
    public Result getLoginUser() {
        User loginUser = SpringContextUtil.getLoginUser();
        if (loginUser == null) {
            return Result.fail(ResultCode.PERMISSION_NO_ACCESS, "未登录");
        }
        // 查询
        User user = userRepository.findUserById(loginUser.getId());
        return Result.success(user);
    }

    @Override
    public Result getArticleCountOfUser(Long userId) {
        User user = new User(userId);
        long count = mongoOperations.count(Query.query(Criteria.where("user").is(user)), Article.class);
        return Result.success(count);
    }

    @Override
    public Result getCount(User user) {
        ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式：模糊查询
                .withIgnoreCase(true) //改变默认大小写忽略方式：忽略大小写
                .withMatcher("username", ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("loginName", ExampleMatcher.GenericPropertyMatchers.contains())
                .withIgnorePaths("id"); //采用“包含匹配”的方式查询
        Example<User> example = Example.of(user, matcher);
        long count = userRepository.count(example);
        return Result.success(count);
    }

    @Override
    public Result getUserPage(Pageable page, User user) {
        if(user.getSchool()!=null && user.getSchool().getId()==0){
            user.setSchool(null);
        }
        //创建匹配器，即如何使用查询条件
        ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式：模糊查询
                .withIgnoreCase(true) //改变默认大小写忽略方式：忽略大小写
                .withMatcher("username", ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("loginName", ExampleMatcher.GenericPropertyMatchers.contains())
                .withIgnorePaths("id"); //采用“包含匹配”的方式查询
        Example<User> example = Example.of(user, matcher);
        Page<User> users = userRepository.findAll(example, page);
        return Result.success(users);
    }

    @Override
    public Result checkLoginName(String loginName) {
        User user = userRepository.findByLoginName(loginName);
        Boolean exists = user != null;
        return Result.success(exists);
    }

    @Override
    public Result uploadImg(MultipartFile file, String token) {
        String dir = PathUtil.basePath + "static/upload/user/images/";
        String tmpFilename = token; // + "." + PathUtil.getFileExt(file.getOriginalFilename());
        try {
            file.transferTo(new File(dir+tmpFilename));
            Map<String, String> result = new HashMap<>();
            result.put("token", token);
            result.put("imageUrl", "/upload/user/images/"+tmpFilename+"?a="+ UUID.randomUUID().toString());
            return Result.success(result);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Result.fail("服务器异常");
    }
}
